# common/snowFaker.py
import time
from functools import lru_cache


class Snowflake:
    def __init__(self, worker_id, data_center_id):
        self.worker_id = worker_id  # 机器ID (0~31)
        self.data_center_id = data_center_id  # 数据中心ID (0~31)
        self.sequence = 0  # 序列号 (0~4095)
        self.last_timestamp = -1  # 上次时间戳

    def next_id(self):
        timestamp = int(time.time() * 1000)
        if timestamp < self.last_timestamp:
            raise Exception(f"时钟回拨，拒绝生成ID。回拨时间：{self.last_timestamp - timestamp}ms")

        if timestamp == self.last_timestamp:
            self.sequence = (self.sequence + 1) & 0xFFF
            if self.sequence == 0:
                timestamp = self._wait_next_millis()
        else:
            self.sequence = 0

        self.last_timestamp = timestamp
        return (
                ((timestamp - 1288834974657) << 22) |
                (self.data_center_id << 17) |
                (self.worker_id << 12) |
                self.sequence
        )

    def _wait_next_millis(self):
        timestamp = int(time.time() * 1000)
        while timestamp <= self.last_timestamp:
            time.sleep(0.001)
            timestamp = int(time.time() * 1000)
        return timestamp


# 单例工厂（最多缓存 32*32=1024 个实例）
@lru_cache(maxsize=1024)
def get_snowflake(worker_id, data_center_id):
    return Snowflake(worker_id, data_center_id)


def get_id_param(worker_id, data_center_id):
    return get_snowflake(worker_id, data_center_id).next_id()